home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / Curses / curses.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-07  |  32.0 KB  |  1,654 lines  |  [TEXT/R*ch]

  1. /*
  2.  *  Module    curses        (Hopefully) machine-independant curses library.
  3.  *  Author    larry gensch, ESQ
  4.  *
  5.  *  Note:   The inspiration for this module was an article by
  6.  *        Allen I. Holub in Dr. Dobbs Journal C Chest column.
  7.  *        Extensive modifications were made by larry gensch
  8.  *        to make the module conform to System V curses.
  9.  *
  10.  *  Copyright (c) 1987, 1988, 1989
  11.  *    by Larry Gensch  /  104 Lowell Road  /  Salem, NH  03079
  12.  *
  13.  *  This code may be included in any work, public or private, with the
  14.  *  exception of creating a commercial curses-compatible subroutine
  15.  *  library.  (In other words, use the code all you want, but please don't
  16.  *  rip off the author by reselling this code as your own).
  17.  *
  18.  *  If you make modifications to this code (specifically, enhancements that
  19.  *  are compatible with System V.x curses), please send them to larry gensch at
  20.  *  the address above to be considered for inclusion in subsequent releases.
  21.  *  Any machine specific implementation modules (similar to v-msdos.c) for
  22.  *  other machines are welcomed.
  23.  */
  24.  
  25. #include "curses.h"
  26. #include <ctype.h>
  27. #include <stdlib.h>
  28.  
  29. /****
  30. * There is no vsscanf function in ANSI standard, so it can't be relied
  31. * on.  Define VSSCANF to the appropriate function name if it is supplied
  32. * with the compiler.  If VSSCANF is not defined, the scanw family of calls
  33. * will not be included in compilation.
  34. ****/
  35.  
  36. #ifdef THINK_C
  37. #    define VSSCANF _vsscanf
  38. #endif
  39.  
  40. #ifdef __WATCOMC__
  41. #    define VSSCANF vsscanf
  42. #endif
  43.  
  44. /*
  45.  * EXPORT is used to show entry points into this module.  Simply grep
  46.  * using the pattern '^EXPORT' to list them out.
  47.  */
  48.  
  49. #ifndef EXPORT
  50. #define EXPORT
  51. #endif
  52.  
  53. /*
  54.  * Exported variables (accessible by user programs):
  55.  */
  56.  
  57. static char prntw_buf[512];
  58.  
  59. EXPORT int    COLS            = 0;
  60. EXPORT int    LINES            = 0;
  61. EXPORT WINDOW*    stdscr;
  62. EXPORT char        *_curses_prntw = prntw_buf;
  63. EXPORT unsigned    _curses_prntw_size    = sizeof(prntw_buf);
  64. EXPORT int        _curses_tab_wid = 8;
  65.  
  66. static bool    Echo    = TRUE;        /* echo()/noecho() state    */
  67. static bool    Cbreak    = FALSE;    /* cbreak()/nocbreak() state    */
  68. static bool    Nl    = TRUE;            /* nl()/nonl() state        */
  69. static bool    Endwin    = TRUE;        /* isendwin() state        */
  70. static bool    Raw    = FALSE;        /* raw()/noraw() state        */
  71. static chtype    Kbbuf[256];        /* Keyboard input buffer    */
  72. static chtype    *Kbptr = Kbbuf;    /* Buffer pointer        */
  73. static int    Kbcount = 0;        /* Nbr characters in buffer    */
  74.  
  75. static chtype ungot_char = -1;    /* Character pushed back by ungetch. */
  76.  
  77. /****
  78. * The following variables are used to communicate between waddch
  79. * and get_input (wgetch) when echo is on:
  80. ****/
  81.  
  82. static int waddch_scroll_cnt;    /* Number of lines window was scrolled up in get_input call. */
  83. static int waddch_end_of_window_flag;    /* Set to TRUE if end of window reached and cannot scroll. */
  84. static int waddch_allow_backspace_up;    /* Set to TRUE to allow backspace character to go up a line. */
  85.  
  86. /*
  87.  * initscr() - initialize the screen and curses internal variables.
  88.  *
  89.  * Returns a pointer to stdscr if successful, otherwise prints a message
  90.  * to stderr and exits.
  91.  */
  92.  
  93. EXPORT WINDOW    *initscr    (void)
  94. {
  95.     if (! Endwin)
  96.         return NULL;
  97.  
  98.     if (! CURS_INIT_FN()) {
  99. #ifdef THINK_C
  100.         maccur_alert_msg("curses: error in terminal initialization.");
  101. #else
  102.         fputs("curses: error in terminal initialization.\n", stderr);
  103. #endif
  104.         exit(1);
  105.     }
  106.  
  107.     if (LINES == 0)
  108.         LINES = 24;
  109.     if (COLS == 0)
  110.         COLS = 80;
  111.  
  112.     stdscr = newwin(0,0,0,0);
  113.     if (stdscr == NULL) {
  114. #ifdef THINK_C
  115.         maccur_alert_msg("curses: cannot allocate stdscr window.");
  116. #else
  117.         fputs("curses: cannot allocate stdscr window.\n", stderr);
  118. #endif
  119.         abort();
  120.     }
  121.  
  122.     Endwin = FALSE;
  123.  
  124.     return stdscr;
  125. }
  126.  
  127. /*
  128.  * endwin() - reset terminal into previous state.  Required before any call to
  129.  * system() or exit().
  130.  */
  131.  
  132. EXPORT int    endwin        (void)
  133. {
  134.     if (stdscr == NULL)
  135.         return ERR;
  136.  
  137.     Endwin = TRUE;
  138.  
  139.     return CURS_END_FN();
  140. }
  141.  
  142. /*
  143.  * isendwin() - determine if endwin() has been called without any subsequent
  144.  * calls to wrefresh().
  145.  */
  146.  
  147. EXPORT bool    isendwin    (void)
  148. {
  149.     return Endwin;
  150. }
  151.  
  152. /* -------------------------------------------- */
  153. /*             Window manipulation              */
  154. /* -------------------------------------------- */
  155.  
  156. /*
  157.  * wrefresh() - Write window to terminal.  Returns ERR if an error occurs.
  158.  */
  159.  
  160. EXPORT int    wrefresh    (WINDOW *win)
  161. {
  162.     if (win != NULL && (win->_flags & _ISPAD) == 0) {
  163.         Endwin = FALSE;
  164.     
  165.         if (win->_flags & (_WINCHANGED | _WINMOVED)) {
  166.             win->_flags &= ~(_WINCHANGED | _WINMOVED);
  167.             return CURS_REFRESH_FN(win, TRUE);
  168.         }
  169.         return OK;
  170.     }
  171.  
  172.     return ERR;
  173. }
  174.  
  175. /*
  176.  * wnoutrefresh() - Update virtual terminal image (physical image updated by
  177.  * doupdate()).
  178.  */
  179.  
  180. EXPORT int    wnoutrefresh    (WINDOW *win)
  181. {
  182.     if (win != NULL && (win->_flags & _ISPAD) == 0) {
  183.         if (win->_flags & (_WINCHANGED | _WINMOVED))
  184.         {
  185.             win->_flags &= ~(_WINCHANGED | _WINMOVED);
  186.             return CURS_REFRESH_FN(win, FALSE);
  187.         }
  188.         return OK;
  189.     }
  190.  
  191.     return ERR;
  192. }
  193.  
  194. /*
  195.  * pad_map: Used by prefresh/pnoutrefresh to determine  what part of
  196.  *            pad to display.  Returns ERR on bad parameters.  Sets _WINMOVED
  197.  *            flag if pad is not mapped to same location as previous call.
  198.  */
  199.  
  200. static int pad_map        (WINDOW *pad, int pminy, int pminx,
  201.                          int sminy, int sminx, int smaxy, int smaxx)
  202. {
  203.     int pmaxx, pmaxy;
  204.  
  205.     pminy = MAX(pminy, 0);
  206.     pminx = MAX(pminx, 0);
  207.     sminy = MAX(sminy, 0);
  208.     sminx = MAX(sminx, 0);
  209.     if (sminx >= smaxx && sminy >= smaxy) return ERR;
  210.  
  211.     pmaxx = pminx + (smaxx - sminx + 1);
  212.     pmaxy = pminy + (smaxy - sminy + 1);
  213.     pmaxx = MIN(pmaxx, pad->_maxx);
  214.     pmaxy = MIN(pmaxy, pad->_maxy);
  215.     
  216.     if (sminy != pad->_begy || sminx != pad->_begx ||
  217.             pminy != pad->_pmap_orgy || pminx != pad->_pmap_orgx ||
  218.             pmaxy != pad->_pmap_maxy || pmaxx != pad->_pmap_maxx)
  219.     {
  220.         pad->_flags |= _WINMOVED;
  221.         pad->_begy = sminy;
  222.         pad->_begx = sminx;
  223.         pad->_pmap_orgy = pminy;
  224.         pad->_pmap_orgx = pminx;
  225.         pad->_pmap_maxy = pmaxy;
  226.         pad->_pmap_maxx = pmaxx;
  227.     }
  228.  
  229.     return OK;
  230. }
  231.  
  232. /*
  233.  * prefresh() - Map and write pad to terminal.  Returns ERR if an error occurs.
  234.  */
  235.  
  236. EXPORT int    prefresh    (WINDOW *pad, int pminy, int pminx,
  237.                          int sminy, int sminx, int smaxy, int smaxx)
  238. {
  239.     if (pad != NULL && (pad->_flags & _ISPAD))
  240.     {
  241.         Endwin = FALSE;
  242.  
  243.         if (pad_map(pad, pminy, pminx, sminy, sminx,
  244.                                     smaxy, smaxx) == ERR)
  245.             return ERR;
  246.  
  247.         if (pad->_flags & (_WINCHANGED | _WINMOVED))
  248.         {
  249.             pad->_flags &= ~(_WINCHANGED | _WINMOVED);
  250.             return CURS_REFRESH_FN(pad, TRUE);
  251.         }
  252.         return OK;
  253.     }
  254.  
  255.     return ERR;
  256. }
  257.  
  258. /*
  259.  * pnoutrefresh() - Update virtual terminal image (physical image updated by
  260.  * doupdate()).
  261.  */
  262.  
  263. EXPORT int    pnoutrefresh    (WINDOW *pad, int pminy, int pminx,
  264.                          int sminy, int sminx, int smaxy, int smaxx)
  265. {
  266.     if (pad != NULL && (pad->_flags & _ISPAD))
  267.     {
  268.         if (pad_map(pad, pminy, pminx, sminy, sminx,
  269.                                     smaxy, smaxx) == ERR)
  270.             return ERR;
  271.  
  272.         if (pad->_flags & (_WINCHANGED | _WINMOVED))
  273.         {
  274.             pad->_flags &= ~(_WINCHANGED | _WINMOVED);
  275.             return CURS_REFRESH_FN(pad, FALSE);
  276.         }
  277.         return OK;
  278.     }
  279.  
  280.     return ERR;
  281. }
  282.  
  283. /*
  284.  * doupdate() - Update the physical terminal image.
  285.  */
  286.  
  287. EXPORT int    doupdate    (void)
  288. {
  289.     Endwin = FALSE;
  290.     return CURS_REFRESH_FN(NULL, TRUE);
  291. }
  292.  
  293. /*
  294.  * window_init() - Initialize window structure.
  295.  */
  296.  
  297. static void window_init    (WINDOW *win, int nlines, int ncols, int beg_y, int beg_x)
  298. {
  299.     win->_cury        = 0;
  300.     win->_curx        = 0;
  301.     win->_maxy        = nlines;
  302.     win->_maxx        = ncols;
  303.        win->_xdim        = ncols;
  304.     win->_begy        = beg_y;
  305.     win->_begx        = beg_x;
  306.     win->_flags        = _WINCHANGED;
  307.     win->_attrs        = 0;
  308.     win->_clear        = FALSE;
  309.     win->_leave        = FALSE;
  310.     win->_scroll    = FALSE;
  311.     win->_use_idl    = FALSE;
  312.     win->_use_keypad    = FALSE;
  313.     win->_use_meta    = FALSE;
  314.     win->_nodelay    = FALSE;
  315.     win->_firstch    = NULL;
  316.     win->_lastch    = NULL;
  317.     win->_notimeout    = FALSE;
  318.     win->_need_idl    = FALSE;
  319.     win->_tmarg        = 0;
  320.     win->_bmarg        = nlines;
  321. }
  322.  
  323. /*
  324.  * newwin() - Create and return a pointer to a new window.
  325.  */
  326.  
  327. EXPORT WINDOW*    newwin        (int nlines, int ncols, int beg_y, int beg_x)
  328. {
  329.     WINDOW    *win;
  330.     chtype    *screen;
  331.     int        i;
  332.  
  333.     if (nlines > LINES || ncols > COLS)
  334.         return NULL;
  335.  
  336.     if (nlines < 1)
  337.         nlines = LINES;
  338.  
  339.     if (ncols < 1)
  340.         ncols = COLS;
  341.  
  342.     if ( (beg_y < 0 || beg_y >= LINES) ||    /* RZ: Was >= on x/y + beg compare to lines/cols */
  343.      (beg_x < 0 || beg_x >= COLS)    ||
  344.          (nlines + beg_y > LINES)    ||
  345.      (ncols + beg_x > COLS) )
  346.         return NULL;
  347.  
  348.     if ((win = calloc(1, sizeof(WINDOW))) == NULL)
  349.         return NULL;
  350.  
  351.     if ((screen = calloc(nlines * ncols, sizeof(chtype))) == NULL) {
  352.         free(win);
  353.         return NULL;
  354.     }
  355.  
  356.     window_init(win, nlines, ncols, beg_y, beg_x);
  357.     win->_y = screen;
  358.  
  359.     for (i = 0; i < nlines * ncols; i++, screen++)
  360.         *screen = ' ';
  361.  
  362.     return win;
  363. }
  364.  
  365. /*
  366.  * subwin() - Create and return a pointer to a new window.
  367.  */
  368.  
  369. EXPORT WINDOW*    subwin        (WINDOW *parnt_win, int nlines, int ncols, int beg_y, int beg_x)
  370. {
  371.     WINDOW *win;
  372.  
  373.     if (parnt_win == NULL)
  374.         return NULL;
  375.  
  376.     if (nlines < 1 || ncols < 1)
  377.         return NULL;
  378.  
  379.     if ( (beg_y < parnt_win->_begy) ||
  380.             (beg_x < parnt_win->_begx) ||
  381.             (nlines + beg_y > parnt_win->_maxy + parnt_win->_begy) ||
  382.             (ncols + beg_x > parnt_win->_maxx + parnt_win->_begx) )
  383.         return NULL;
  384.  
  385.     if ((win = calloc(1, sizeof(WINDOW))) == NULL)
  386.         return NULL;
  387.  
  388.     window_init(win, nlines, ncols, beg_y, beg_x);
  389.     win->_flags |= _SUBWIN;
  390.     win->_y = parnt_win->_y + ((beg_y - parnt_win->_begy) * parnt_win->_xdim +
  391.                                 beg_x - parnt_win->_begx);
  392.     win->_xdim = parnt_win->_maxx;
  393.  
  394.     return win;
  395. }
  396.  
  397. /*
  398.  * newpad() - Create and return a pointer to a new pad.
  399.  */
  400.  
  401. EXPORT WINDOW*    newpad        (int nlines, int ncols)
  402. {
  403.     WINDOW    *pad;
  404.     chtype    *screen;
  405.     int        i;
  406.  
  407.     if ( nlines < 1 || ncols < 1 )
  408.         return NULL;
  409.  
  410.     if ((pad = calloc(1, sizeof(WINDOW))) == NULL)
  411.         return NULL;
  412.  
  413.     if ((screen = calloc(nlines * ncols, sizeof(chtype))) == NULL) {
  414.         free(pad);
  415.         return NULL;
  416.     }
  417.  
  418.     window_init(pad, nlines, ncols, 0, 0);
  419.     pad->_pmap_orgy = 0;
  420.     pad->_pmap_orgx = 0;
  421.     pad->_pmap_maxy = LINES;
  422.     pad->_pmap_maxx = COLS;
  423.     pad->_flags |= _ISPAD;
  424.     pad->_y = screen;
  425.  
  426.     for (i = 0; i < nlines * ncols; i++, screen++)
  427.         *screen = ' ';
  428.  
  429.     return pad;
  430. }
  431.  
  432. /*
  433.  * subpad() - Create and return a pointer to a pad inside another pad.
  434.  */
  435.  
  436. EXPORT WINDOW*    subpad        (WINDOW *parnt_pad, int nlines, int ncols, int beg_y, int beg_x)
  437. {
  438.     WINDOW *pad;
  439.  
  440.     if (parnt_pad == NULL || (parnt_pad->_flags & _ISPAD) == 0)
  441.         return NULL;
  442.  
  443.     if (nlines < 1 || ncols < 1)
  444.         return NULL;
  445.  
  446.     if ( (beg_y < 0) ||
  447.             (beg_x < 0) ||
  448.             (nlines + beg_y > parnt_pad->_maxy) ||
  449.             (ncols + beg_x > parnt_pad->_maxx) )
  450.         return NULL;
  451.  
  452.     if ((pad = calloc(1, sizeof(WINDOW))) == NULL)
  453.         return NULL;
  454.  
  455.     window_init(pad, nlines, ncols, beg_y, beg_x);
  456.     pad->_pmap_orgy = parnt_pad->_pmap_orgy;
  457.     pad->_pmap_orgx = parnt_pad->_pmap_orgx;
  458.     pad->_pmap_maxy = parnt_pad->_pmap_maxy;
  459.     pad->_pmap_maxx = parnt_pad->_pmap_maxx;
  460.     pad->_flags |= (_SUBWIN | _ISPAD);
  461.     pad->_y = parnt_pad->_y + (beg_y * parnt_pad->_xdim + beg_x);
  462.     pad->_xdim = parnt_pad->_maxx;
  463.  
  464.     return pad;
  465. }
  466.  
  467. /*
  468.  * mvwin() - move window so that the upper left corner will be at the specified
  469.  * position.
  470.  */
  471.  
  472. EXPORT int    mvwin        (WINDOW *win, int y, int x)
  473. {
  474.     if (win == NULL || (win->_flags & _ISPAD))
  475.         return ERR;
  476.  
  477.     if ( (x + win->_maxx > COLS)    ||
  478.          (y + win->_maxy > LINES) )    /* RZ -- Check was >=, eliminated OK mappings. */
  479.         return ERR;
  480.  
  481.     win->_begx = x;
  482.     win->_begy = y;
  483.     win->_flags |= _WINMOVED;
  484.  
  485.     return OK;
  486. }
  487.  
  488. /*
  489.  * delwin() - delete the named window, freeing all memory associated with it.
  490.  */
  491.  
  492. EXPORT int    delwin        (WINDOW *win)
  493. {
  494.     if (win == NULL)
  495.         return ERR;
  496.  
  497.     free(win->_y);
  498.     free(win);
  499.  
  500.     return OK;
  501. }
  502.  
  503. /*
  504.  * waddch() - Output the specified character to the specified window.
  505.  *
  506.  * Note:  The "unctrl" routine in the default: case below is
  507.  *      specific to the ASCII character set.
  508.  *
  509.  */
  510.  
  511. EXPORT int    waddch        (WINDOW *win, chtype ch)
  512. {
  513.     int        rval = OK;
  514.     chtype c, attr;
  515.  
  516.     if (win == NULL)
  517.         return ERR;
  518.  
  519.     win->_flags |= _WINCHANGED;
  520.  
  521.     waddch_scroll_cnt = 0;
  522.     waddch_end_of_window_flag = FALSE;
  523.  
  524.     c = (ch & A_CHARTEXT);
  525.     attr = (ch & A_ATTRIBUTES);
  526.     switch (c | (ch & A_ALTCHARSET))
  527.     {
  528.         case '\b':
  529.             if (win->_curx > 0 || (waddch_allow_backspace_up && win->_cury > 0))
  530.             {
  531.                 win->_y[win->_cury*win->_xdim + --win->_curx] = ' ' | win->_attrs;
  532.                 if (win->_curx < 0)
  533.                 {
  534.                     win->_cury--;
  535.                     win->_curx = win->_maxx - 1;
  536.                 }
  537.             }
  538.             else rval = ERR;
  539.     
  540.             break;
  541.  
  542.         case '\t':
  543.             do {
  544.                 waddch(win, ' ' | attr);
  545.             } while (win->_curx % _curses_tab_wid &&
  546.                      win->_curx > 0 && !waddch_end_of_window_flag);    /* Don't let tab spill into new line. */
  547.             break;
  548.     
  549.         case '\r':
  550.             win->_curx = 0;
  551.             break;
  552.     
  553.         default:
  554.             if ( ( (ch & A_ALTCHARSET) == 0) &&
  555.                     iscntrl(c))
  556.             {
  557.                 waddch(win, '^' | attr);
  558.                 ch = ((c == 0x7f) ? '?' : c + 'A' - 1) | attr;
  559.             }
  560.     
  561.             win->_y[win->_cury*win->_xdim+win->_curx] = ch | win->_attrs;
  562.     
  563.             if (++(win->_curx) < win->_maxx)
  564.                 break;
  565.     
  566.             /* fall through to newline */
  567.     
  568.         case '\n':
  569.             if (ch == '\n')
  570.                 wclrtoeol(win);
  571.  
  572.             win->_curx = 0;
  573.             win->_cury++;
  574.  
  575.             if (win->_scroll && win->_cury >= win->_bmarg )
  576.             {
  577.                 if ((rval = scroll(win)) != ERR)
  578.                 {
  579.                     win->_cury = win->_bmarg - 1;
  580.                     waddch_scroll_cnt++;
  581.                 }
  582.             }
  583.     
  584.             break;
  585.     }
  586.  
  587.     if (win->_cury >= win->_maxy)
  588.     {
  589.         win->_cury = win->_maxy - 1;
  590.         win->_curx = win->_maxx - 1;
  591.         waddch_end_of_window_flag = TRUE;
  592.         rval = ERR;
  593.     }
  594.  
  595.     win->_flags |= _WINCHANGED;
  596.     waddch_allow_backspace_up = FALSE;
  597.     return rval;
  598. }
  599.  
  600. /*
  601.  * wechochar() - waddch() followed by refresh()
  602.  */
  603.  
  604. EXPORT int    wechochar    (WINDOW *win, chtype ch)
  605. {
  606.     waddch(win,ch);
  607.     return wrefresh(win);
  608. }
  609.  
  610. /*
  611.  * pechochar() - waddch() followed by prefresh()
  612.  */
  613.  
  614. EXPORT int    pechochar    (WINDOW *pad, chtype ch)
  615. {
  616.     waddch(pad,ch);
  617.     return prefresh(pad, pad->_pmap_orgy, pad->_pmap_orgx,
  618.                                 pad->_begy, pad->_begx,
  619.                                 pad->_begy + pad->_pmap_maxy - pad->_pmap_orgy - 1,
  620.                                 pad->_begx + pad->_pmap_maxx - pad->_pmap_orgx - 1);
  621. }
  622.  
  623. /*
  624.  * waddstr() - Write the characters in the string to the window.
  625.  */
  626.  
  627. EXPORT int    waddstr        (WINDOW *win, char *str)
  628. {
  629.     int        rval = OK;
  630.  
  631.     while (*str)
  632.         if (waddch(win, (chtype) *(str++)) == ERR)
  633.             rval = ERR;
  634.  
  635.     return rval;
  636. }
  637.  
  638. /*
  639.  * wattroff() - Turn off the specified attributes in the window.
  640.  */
  641.  
  642. EXPORT int    wattroff    (WINDOW *win, chtype attrs)
  643. {
  644.     if (win == NULL)
  645.         return ERR;
  646.  
  647.     win->_attrs &= ~(attrs & A_ATTRIBUTES);
  648.     return OK;
  649. }
  650.  
  651. /*
  652.  * wattron() - Turn on the specified attributes in the window.
  653.  */
  654.  
  655. EXPORT int    wattron        (WINDOW *win, chtype attrs)
  656. {
  657.     if (win == NULL)
  658.         return ERR;
  659.  
  660.     win->_attrs |= (attrs & A_ATTRIBUTES);
  661.     return OK;
  662. }
  663.  
  664. /*
  665.  * wattrset() - Set the specified attributes in the window.
  666.  */
  667.  
  668. EXPORT int    wattrset    (WINDOW *win, chtype attrs)
  669. {
  670.     if (win == NULL)
  671.         return ERR;
  672.  
  673.     win->_attrs = (attrs & A_ATTRIBUTES);
  674.     return OK;
  675. }
  676.  
  677. /*
  678.  * wstandout() - Turn on standout mode.
  679.  */
  680.  
  681. EXPORT int    wstandout    (WINDOW *win)
  682. {
  683.     return wattron(win, A_STANDOUT);
  684. }
  685.  
  686. /*
  687.  * wstandend() - Turn off all attributes.
  688.  */
  689.  
  690. EXPORT int    wstandend    (WINDOW *win)
  691. {
  692.     return wattrset(win, A_NORMAL);
  693. }
  694.  
  695. /*
  696.  * beep() - Sound the audible alarm()
  697.  */
  698.  
  699. EXPORT int    beep        (void)
  700. {
  701.     CURS_BEEP_FN(FALSE);
  702.     return OK;
  703. }
  704.  
  705. /*
  706.  * flash() - Flash the screen (alternately, sound the alarm)
  707.  */
  708.  
  709. EXPORT int    alarm        (void)
  710. {
  711.     CURS_BEEP_FN(TRUE);
  712.     return OK;
  713. }
  714.  
  715. /*
  716.  * box() - Draw a box around the edge of the window.
  717.  */
  718.  
  719. EXPORT int    box        (WINDOW *win, chtype vertch, chtype horch)
  720. {
  721.     chtype    ul, ur, ll, lr;
  722.     int        i;
  723.     int        ox, oy;
  724.     bool    os;
  725.  
  726.     if (win == NULL)
  727.         return ERR;
  728.  
  729.     if (horch == '\b' || vertch == '\b')                /* These could cause infinite loop. */
  730.         return ERR;
  731.  
  732.     if (vertch == 0)
  733.         vertch = ACS_VLINE;
  734.     if (horch == 0)
  735.         horch = ACS_HLINE;
  736.  
  737.     if (vertch == ACS_VLINE && horch == ACS_HLINE) {
  738.         ul = ACS_ULCORNER;
  739.         ur = ACS_URCORNER;
  740.         ll = ACS_LLCORNER;
  741.         lr = ACS_LRCORNER;
  742.     }
  743.     else
  744.         ul = ur = ll = lr = horch;
  745.  
  746.     ox = win->_cury;
  747.     oy = win->_curx;
  748.     os = win->_scroll;
  749.  
  750.     wmove(win, 0, 0);
  751.     waddch(win, ul);
  752.     win->_scroll = FALSE;
  753.  
  754.     for (i = 2; i < win->_maxx; i++)
  755.         waddch(win, horch);
  756.  
  757.     waddch(win, ur);
  758.  
  759.     for (i = 1; i < win->_maxy - 1; i++) {
  760.         wmove(win, i, 0);
  761.         waddch(win, vertch);
  762.         wmove(win, i, win->_maxx-1);
  763.         waddch(win, vertch);
  764.     }
  765.  
  766.     mvwaddch(win, win->_maxy - 1, 0, ll);
  767.  
  768.     for (i = 2; i < win->_maxx; i++)
  769.         waddch(win, horch);
  770.  
  771.     waddch(win, lr);
  772.  
  773.     win->_cury   = ox;
  774.     win->_curx   = oy;
  775.     win->_scroll = os;
  776.     win->_flags |= _WINCHANGED;
  777.  
  778.     return OK;
  779. }
  780.  
  781. /*
  782.  * werase() - Erase a window.
  783.  */
  784.  
  785. EXPORT int    werase        (WINDOW *win)
  786. {
  787.     int        i, i_rw;
  788.     chtype    ch;
  789.     chtype    *screen, *dst_ptr;
  790.  
  791.     if (win == NULL)
  792.         return ERR;
  793.  
  794.     ch = ' ';
  795.     screen = win->_y;
  796.     i = win->_maxx * win->_maxy;
  797.  
  798.     for (i_rw = 0; i_rw < win->_maxy; i_rw++)            /* Have to do row-by-row because of possible subwin/pad. */
  799.     {
  800.         dst_ptr = screen + i_rw * win->_xdim;
  801.         for (i = 0; i < win->_maxx; i++)
  802.             *(dst_ptr + i) = ch;
  803.     }
  804.  
  805.     win->_flags |= _WINCHANGED;
  806.     return OK;
  807. }
  808.  
  809. /*
  810.  * wclear() - Clear the window (functionally identical to erase())
  811.  */
  812.  
  813. EXPORT int    wclear        (WINDOW *win)
  814. {
  815.     return werase(win);
  816. }
  817.  
  818. /*
  819.  * wclrtobot() - Clear from cursor position to the bottom of the window.
  820.  */
  821.  
  822. EXPORT int    wclrtobot    (WINDOW *win)
  823. {
  824.     int        i, i_rw;
  825.     int        max;
  826.     chtype    *dst_ptr;
  827.     chtype    ch;
  828.  
  829.     if (win == NULL)
  830.         return ERR;
  831.  
  832.     win->_flags |= _WINCHANGED;
  833.  
  834.     ch = ' ';
  835.  
  836.     for (i_rw = win->_cury; i_rw < win->_maxy; i_rw++)        /* Have to do row-by-row because of possible subwin/pad. */
  837.     {
  838.         dst_ptr = win->_y + i_rw * win->_xdim;
  839.         for (i = (i_rw == win->_cury ? win->_curx : 0); i < win->_maxx; i++)
  840.             *(dst_ptr + i) = ch;
  841.     }
  842.  
  843.  
  844.     return OK;
  845. }
  846.  
  847. /*
  848.  * wclrtoeol() - Clear from cursor position to end of line in window.
  849.  */
  850.  
  851. EXPORT int    wclrtoeol    (WINDOW *win)
  852. {
  853.     int        i;
  854.     chtype    *screen;
  855.     chtype    ch;
  856.  
  857.     if (win == NULL)
  858.         return ERR;
  859.  
  860.     if (win->_cury >= win->_maxy)
  861.         return ERR;
  862.  
  863.     win->_flags |= _WINCHANGED;
  864.  
  865.     screen = win->_y + (win->_cury * win->_xdim);
  866.     ch = ' ';
  867.  
  868.     for (i = win->_curx; i < win->_maxx; i++)
  869.         *(screen + i) = ch;
  870.  
  871.     return OK;
  872. }
  873.  
  874. /*
  875.  * delch() - Delete character under cursor, moving all characters to end of
  876.  * line in the window to the right one character.
  877.  */
  878.  
  879. EXPORT int    wdelch        (WINDOW *win)
  880. {
  881.     chtype    *dst_ptr;
  882.     int n;
  883.  
  884.     if (win == NULL)
  885.         return ERR;
  886.  
  887.     win->_flags |= _WINCHANGED;
  888.  
  889.     dst_ptr = win->_y + (win->_cury * win->_xdim + win->_curx);
  890.     n = win->_maxx - win->_curx - 1;
  891.     memmove(dst_ptr, dst_ptr + 1, n * sizeof(chtype));
  892.     *(dst_ptr + n) = ' ' | win->_attrs;
  893.  
  894.     return OK;
  895. }
  896.  
  897. /*
  898.  * wdeleteln() - Delete the line containing the cursor, moving all subsequent
  899.  * lines in the window up one line.
  900.  */
  901.  
  902. EXPORT int    wdeleteln    (WINDOW *win)
  903. {
  904.     int        i, i_rw;
  905.     chtype    *dst_ptr;
  906.     chtype    ch;
  907.  
  908.     if (win == NULL)
  909.         return ERR;
  910.  
  911.     win->_flags |= _WINCHANGED;
  912.  
  913.     for (i_rw = win->_cury; i_rw < win->_maxy - 1; i_rw++)
  914.     {
  915.         dst_ptr = win->_y + (i_rw * win->_xdim);
  916.         memcpy(dst_ptr, dst_ptr + win->_xdim, win->_maxx * sizeof(chtype));
  917.     }
  918.  
  919.     dst_ptr = win->_y + ((win->_maxy - 1) * win->_xdim);
  920.     for (i = 0; i < win->_maxx; i++)
  921.         *(dst_ptr + i) = ch;
  922.  
  923.     return OK;
  924. }
  925.  
  926. /*
  927.  * winsch() - Insert a character at the cursor position in the window, moving
  928.  * all subsequent characters (to end of line) to the right one character.
  929.  */
  930.  
  931. EXPORT int    winsch        (WINDOW *win, chtype ch)
  932. {
  933.     chtype    *src_ptr;
  934.  
  935.     if (win == NULL)
  936.         return ERR;
  937.  
  938.     win->_flags |= _WINCHANGED;
  939.  
  940.     src_ptr = win->_y + (win->_cury * win->_xdim + win->_curx);
  941.     memmove(src_ptr + 1, src_ptr, (win->_maxx - win->_curx - 1) * sizeof(chtype));
  942.     *src_ptr = ch | win->_attrs;
  943.  
  944.     return OK;
  945. }
  946.  
  947. /*
  948.  * winsertln() - Insert a blank line above current line. (had a bug)
  949.  */
  950.  
  951. EXPORT int    winsertln    (WINDOW *win)
  952. {
  953.     int        i, i_rw;
  954.     chtype    *dst_ptr;
  955.     chtype    ch;
  956.  
  957.     if (win == NULL)
  958.         return ERR;
  959.  
  960.     win->_flags |= _WINCHANGED;
  961.  
  962.     ch = ' ';
  963.  
  964.     for (i_rw = win->_cury + 1; i_rw < win->_maxy; i_rw++)
  965.     {
  966.         dst_ptr = win->_y + (i_rw * win->_xdim);
  967.         memcpy(dst_ptr, dst_ptr - win->_xdim, win->_maxx * sizeof(chtype));
  968.     }
  969.  
  970.     dst_ptr = win->_y + (win->_cury * win->_xdim);
  971.     for (i = 0; i < win->_maxx; i++)
  972.         *(dst_ptr + i) = ch;
  973.  
  974.     return OK;
  975. }
  976.  
  977. /*
  978.  * printw() - Print a printf()-formatted string onto stdscr.
  979.  */
  980.  
  981. EXPORT int    printw        (char *fmt, ...)
  982. {
  983.     va_list args;
  984.  
  985.     va_start(args, fmt);
  986.     vsprintf(_curses_prntw, fmt, args);
  987.     va_end(args);
  988.  
  989.     return addstr(_curses_prntw);
  990. }
  991.  
  992. /*
  993.  * mvprintw() - Print a printf()-formatted string onto stdscr after positioning.
  994.  */
  995.  
  996. EXPORT int    mvprintw    (int y, int x, char *fmt, ...)
  997. {
  998.     va_list args;
  999.  
  1000.     move(y, x);
  1001.  
  1002.     va_start(args, fmt);
  1003.     vsprintf(_curses_prntw, fmt, args);
  1004.     va_end(args);
  1005.  
  1006.     return addstr(_curses_prntw);
  1007. }
  1008.  
  1009. /*
  1010.  * wprintw() - Print a printf()-formatted string onto a window.
  1011.  */
  1012.  
  1013. EXPORT int    wprintw        (WINDOW *win, char *fmt, ...)
  1014. {
  1015.     va_list args;
  1016.  
  1017.     va_start(args, fmt);
  1018.     vsprintf(_curses_prntw, fmt, args);
  1019.     va_end(args);
  1020.  
  1021.     return waddstr(win, _curses_prntw);
  1022. }
  1023.  
  1024. /*
  1025.  * mvwprintw() - Print a printf()-formatted string onto a window after positioning.
  1026.  */
  1027.  
  1028. EXPORT int    mvwprintw    (WINDOW *win, int y, int x, char *fmt, ...)
  1029. {
  1030.     va_list args;
  1031.  
  1032.     wmove(win, y, x);
  1033.  
  1034.     va_start(args, fmt);
  1035.     vsprintf(_curses_prntw, fmt, args);
  1036.     va_end(args);
  1037.  
  1038.     return waddstr(win, _curses_prntw);
  1039. }
  1040.  
  1041. /*
  1042.  * vwprintw() - Print a printf()-formatted string onto a window using a
  1043.  * variable argument list.
  1044.  */
  1045.  
  1046. EXPORT int    vwprintw    (WINDOW *win, char *fmt, va_list ap)
  1047. {
  1048.     va_list args;
  1049.  
  1050.     vsprintf(_curses_prntw, fmt, ap);
  1051.  
  1052.     return waddstr(win, _curses_prntw);
  1053. }
  1054.  
  1055. /*
  1056.  * scroll() - Scroll a window up one line.
  1057.  *    This is the same as wdeleteln on the top scrolling char.
  1058.  */
  1059.  
  1060. EXPORT int    scroll        (WINDOW *win)
  1061. {
  1062.     int        i, i_rw;
  1063.     chtype    *dst_ptr;
  1064.     chtype    ch;
  1065.  
  1066.     if (win == NULL)
  1067.         return ERR;
  1068.  
  1069.     if (!win->_scroll)
  1070.         return ERR;
  1071.  
  1072.     win->_flags |= _WINCHANGED;
  1073.  
  1074.     ch = ' ' | win->_attrs;
  1075.  
  1076.     for (i_rw = win->_tmarg; i_rw < win->_bmarg - 1; i_rw++)
  1077.     {
  1078.         dst_ptr = win->_y + (i_rw * win->_xdim);
  1079.         memcpy(dst_ptr, dst_ptr + win->_xdim, win->_maxx * sizeof(chtype));
  1080.     }
  1081.  
  1082.     dst_ptr = win->_y + ((win->_bmarg - 1) * win->_xdim);
  1083.     for (i = 0; i < win->_maxx; i++)
  1084.         *(dst_ptr + i) = ch;
  1085.  
  1086.     return OK;
  1087. }
  1088.  
  1089. /*
  1090.  * touchwin() - Pretend that the window has been modified since last refresh().
  1091.  */
  1092.  
  1093. EXPORT int    touchwin    (WINDOW *win)
  1094. {
  1095.     if (win == NULL)
  1096.         return ERR;
  1097.  
  1098.     win->_flags |= _WINCHANGED;
  1099.  
  1100.     return OK;
  1101. }
  1102.  
  1103. /*
  1104.  * touchline() - Functionally identical to touchwin()
  1105.  */
  1106.  
  1107. EXPORT int    touchline    (WINDOW *win, int start, int count)
  1108. {
  1109.     return touchwin(win);
  1110. }
  1111.  
  1112. /*
  1113.  * wmove() - Set the cursor position within a window.
  1114.  */
  1115.  
  1116. EXPORT int    wmove        (WINDOW *win, int ypos, int xpos)
  1117. {
  1118.     if (win == NULL)
  1119.         return ERR;
  1120.  
  1121.     if ( (xpos < 0 || xpos >= win->_maxx) ||
  1122.      (ypos < 0 || ypos >= win->_maxy) )
  1123.         return ERR;
  1124.  
  1125.     win->_curx = xpos;
  1126.     win->_cury = ypos;
  1127.  
  1128.     return OK;
  1129. }
  1130.  
  1131. /*
  1132.  * copywin() - Move text from one window to another.
  1133.  */
  1134.  
  1135. EXPORT int copywin        (WINDOW *src_win, WINDOW *dst_win,
  1136.                          int sminy, int sminx, int dminy, int dminx,
  1137.                          int dmaxy, int dmaxx, bool overlay_flag)
  1138. {
  1139.     int nrows, nchars, i, j;
  1140.     chtype *src_ptr, *dst_ptr;
  1141.  
  1142.     sminy = MAX(sminy, 0);
  1143.     sminx = MAX(sminx, 0);
  1144.     dminy = MAX(dminy, 0);
  1145.     dminx = MAX(dminx, 0);
  1146.  
  1147.     if (sminy >= src_win->_maxy || sminx >= src_win->_maxx ||
  1148.             dminy >= dst_win->_maxy || dminx >= dst_win->_maxx ||
  1149.             dminy >= dmaxy || dminx >= dmaxx)
  1150.         return ERR;
  1151.  
  1152.     dst_win->_flags |= _WINCHANGED;
  1153.  
  1154.     nrows = MIN(dmaxy + 1, dst_win->_maxy) - dminy;
  1155.     nrows = MIN(nrows, src_win->_maxy - sminy);
  1156.     nchars = MIN(dmaxx + 1, dst_win->_maxx) - dminx;
  1157.     nchars = MIN(nchars, src_win->_maxx - sminx);
  1158.     src_ptr = src_win->_y + (sminy * src_win->_xdim) + sminx;
  1159.     dst_ptr = dst_win->_y + (dminy * dst_win->_xdim) + dminx;
  1160.  
  1161.     for (i = 0; i < nrows; i++)
  1162.     {
  1163.         if (overlay_flag)
  1164.         {
  1165.             for (j = 0; j < nchars; j++)
  1166.                 if ((*src_ptr & A_CHARTEXT) != ' ')
  1167.                     *(dst_ptr + j) = *(src_ptr + j);
  1168.         }
  1169.         else
  1170.             memmove(dst_ptr, src_ptr, nchars * sizeof(chtype));
  1171.  
  1172.         src_ptr += src_win->_xdim;
  1173.         dst_ptr += dst_win->_xdim;
  1174.     }
  1175.  
  1176.     return OK;
  1177. }
  1178.  
  1179. /*
  1180.  * overwrite()/overlay() - Copy one window onto another.  If either is
  1181.  *    a pad, the copy is done as if the two windows/pads have the same
  1182.  *    upper left corner.
  1183.  */
  1184.  
  1185. EXPORT int    overwrite    (WINDOW *src_win, WINDOW *dst_win)
  1186. {
  1187.  
  1188.     if ((src_win->_flags & _ISPAD) || (dst_win->_flags & _ISPAD))
  1189.         return copywin(src_win, dst_win, 0, 0, 0, 0,
  1190.                                     dst_win->_maxy - 1,
  1191.                                     dst_win->_maxx - 1,
  1192.                                     FALSE);
  1193.     else
  1194.         return copywin(src_win, dst_win, 0, 0,
  1195.                                     src_win->_begy - dst_win->_begy,
  1196.                                     src_win->_begx - dst_win->_begx,
  1197.                                     src_win->_maxy + src_win->_begy - dst_win->_begy - 1,
  1198.                                     src_win->_maxx + src_win->_begx - dst_win->_begx - 1,
  1199.                                     FALSE);
  1200. }
  1201.  
  1202. EXPORT int    overlay        (WINDOW *src_win, WINDOW *dst_win)
  1203. {
  1204.  
  1205.     if ((src_win->_flags & _ISPAD) || (dst_win->_flags & _ISPAD))
  1206.         return copywin(src_win, dst_win, 0, 0, 0, 0,
  1207.                                     dst_win->_maxy - 1,
  1208.                                     dst_win->_maxx - 1,
  1209.                                     TRUE);
  1210.     else
  1211.         return copywin(src_win, dst_win, 0, 0,
  1212.                                     src_win->_begy - dst_win->_begy,
  1213.                                     src_win->_begx - dst_win->_begx,
  1214.                                     src_win->_maxy + src_win->_begy - dst_win->_begy - 1,
  1215.                                     src_win->_maxx + src_win->_begx - dst_win->_begx - 1,
  1216.                                     TRUE);
  1217. }
  1218.  
  1219. /*
  1220.  * cbreak()/nocbreak() - Put the terminal into cbreak mode (ignored currently)
  1221.  */
  1222.  
  1223. EXPORT int    cbreak        (void)
  1224. {
  1225.     return (Cbreak = TRUE);
  1226. }
  1227.  
  1228. EXPORT int    nocbreak    (void)
  1229. {
  1230.     return (Cbreak = FALSE);
  1231. }
  1232.  
  1233. /*
  1234.  * echo()/noecho() - Echo characters as they are typed
  1235.  */
  1236.  
  1237. EXPORT int    echo        (void)
  1238. {
  1239.     return (Echo = TRUE);
  1240. }
  1241.  
  1242. EXPORT int    noecho        (void)
  1243. {
  1244.     return (Echo = FALSE);
  1245. }
  1246.  
  1247. /*
  1248.  * nl()/nonl() - CR -> NL mapping
  1249.  */
  1250.  
  1251. EXPORT int    nl        (void)
  1252. {
  1253.     return (Nl = TRUE);
  1254. }
  1255.  
  1256. EXPORT int    nonl        (void)
  1257. {
  1258.     return (Nl = FALSE);
  1259. }
  1260.  
  1261. /*
  1262.  * halfdelay() - ignored
  1263.  */
  1264.  
  1265. EXPORT int    halfdelay    (int tenths)
  1266. {
  1267.     return OK;
  1268. }
  1269.  
  1270. /*
  1271.  * intrflush() - Determines whether or not to flush input on interrupt.
  1272.  */
  1273.  
  1274. EXPORT int    intrflush    (WINDOW *win, bool flag)
  1275. {
  1276.     if (win == NULL)
  1277.     return ERR;
  1278.     win->_flags |= _FLUSH;
  1279.     return OK;
  1280. }
  1281.  
  1282. /*
  1283.  * keypad() - Turns on/off special key mapping.
  1284.  */
  1285.  
  1286. EXPORT int    keypad        (WINDOW *win, bool flag)
  1287. {
  1288.     if (win == NULL)
  1289.     return ERR;
  1290.     win->_use_keypad = flag;
  1291.     return OK;
  1292. }
  1293.  
  1294. /*
  1295.  * meta() - Turns on/off meta mapping.
  1296.  */
  1297.  
  1298. EXPORT int    meta        (WINDOW *win, bool flag)
  1299. {
  1300.     if (win == NULL)
  1301.     return ERR;
  1302.     win->_use_meta = flag;
  1303.     return OK;
  1304. }
  1305.  
  1306. /*
  1307.  * nodelay() - Turns wgetch() into a non-blocking call.
  1308.  */
  1309.  
  1310. EXPORT int    nodelay        (WINDOW *win, bool flag)
  1311. {
  1312.     if (win == NULL)
  1313.     return ERR;
  1314.  
  1315.     win->_nodelay = flag;
  1316.     return OK;
  1317. }
  1318.  
  1319. /*
  1320.  * notimeout() - Turn on/off escape sequence timing.
  1321.  */
  1322.  
  1323. EXPORT int    notimeout    (WINDOW *win, bool flag)
  1324. {
  1325.     if (win == NULL)
  1326.     return ERR;
  1327.     win->_notimeout = flag;
  1328.     return OK;
  1329. }
  1330.  
  1331. /*
  1332.  * raw()/noraw() - Return characters as they are received.
  1333.  */
  1334.  
  1335. EXPORT int    raw        (void)
  1336. {
  1337.     return (Raw = TRUE);
  1338. }
  1339.  
  1340. EXPORT int    noraw        (void)
  1341. {
  1342.     return (Raw = FALSE);
  1343. }
  1344.  
  1345. /*
  1346.  * get_input() - Get input from keyboard.  Does an implicit refresh of screen.
  1347.  */
  1348.  
  1349. static int    get_input        (WINDOW *win, chtype *chrs, int chrs_max,
  1350.                              bool cbrk_flag, bool raw_flag)
  1351. {
  1352.     chtype    c, save_attr;
  1353.     int c_pos, start_col, start_row, i;
  1354.  
  1355.     c_pos = 0;
  1356.     start_col = win->_curx;
  1357.     start_row = win->_cury;
  1358.  
  1359.     wrefresh(win);
  1360.  
  1361.     for (;;)
  1362.     {
  1363.         c = CURS_KBINP_FN(win, raw_flag, cbrk_flag);
  1364.     
  1365.         if (c == ERR)
  1366.             return ERR;
  1367.     
  1368.         if (Nl && c == '\r')
  1369.             c = '\n';
  1370.  
  1371.         if (cbrk_flag)
  1372.         {
  1373.             *(chrs + c_pos++) = c;
  1374.             if (Echo)
  1375.                 waddch(win, c);
  1376.         }
  1377.         else
  1378.         {
  1379.             switch (c)
  1380.             {
  1381.                 case '\b':                /* Backspace (delete previous character) key. */
  1382.                     if (!raw_flag)        /* Raw mode will fall through to default case. */
  1383.                     {
  1384.                         if (c_pos <= 0) {
  1385.                             beep();
  1386.                             break;
  1387.                         }
  1388.         
  1389.                         if (Echo)
  1390.                         {
  1391.                             waddch_allow_backspace_up = TRUE;
  1392.                             waddch(win, c);
  1393.                             if (iscntrl( (*(chrs + (c_pos - 1))) & A_CHARTEXT ))
  1394.                                {
  1395.                                 waddch_allow_backspace_up = TRUE;
  1396.                                 waddch(win, c);
  1397.                             }
  1398.                         }
  1399.                         c_pos--;
  1400.                         break;
  1401.                     }
  1402.  
  1403.                 case '\025':            /* ctrl-U => Clear input. */
  1404.                     if (!raw_flag)        /* Raw mode will fall through to default case. */
  1405.                     {
  1406.                         if (Echo)
  1407.                         {
  1408.                             win->_curx = start_col;
  1409.                             win->_cury = start_row;
  1410.                             save_attr = win->_attrs;
  1411.                             win->_attrs = 0;
  1412.                             for (i = 0; i < c_pos; i++)
  1413.                             {
  1414.                                 if ( ((*(chrs + i)) & A_CHARTEXT) == '\t')
  1415.                                     waddch(win, '\t');
  1416.                                 else
  1417.                                 {
  1418.                                     waddch(win, ' ');
  1419.                                     if (iscntrl((*(chrs + i)) & A_CHARTEXT))
  1420.                                         waddch(win, ' ');
  1421.                                 }
  1422.                                 if (waddch_end_of_window_flag) break;
  1423.                             }
  1424.                             win->_curx = start_col;
  1425.                             win->_cury = start_row;
  1426.                             win->_attrs = save_attr;
  1427.                         }
  1428.                         c_pos = 0;
  1429.                         break;
  1430.                     }
  1431.  
  1432.                 default:
  1433.                     if (chrs_max != -1 && c_pos >= chrs_max)
  1434.                     {
  1435.                         beep();
  1436.                         break;
  1437.                     }
  1438.                     *(chrs + c_pos++) = c;
  1439.                     if (Echo)
  1440.                     {
  1441.                         waddch(win, c);
  1442.                         start_row -= waddch_scroll_cnt;
  1443.                     }
  1444.                     break;
  1445.             }
  1446.         }
  1447.         if (Echo)
  1448.             wrefresh(win);
  1449.         if (cbrk_flag || c == '\n' || c == '\r')
  1450.             return c_pos;
  1451.     }
  1452. }
  1453.  
  1454. /*
  1455.  * ungetch() - Push back a character to be returned by next
  1456.  *    call to wgetch or wgetstr.
  1457.  */
  1458.  
  1459. EXPORT int ungetch        (chtype ch)
  1460. {
  1461.     ungot_char = ch;
  1462.  
  1463.     return ch;
  1464. }
  1465.  
  1466. /*
  1467.  * wgetch() - Get character from keyboard.
  1468.  */
  1469.  
  1470. EXPORT int    wgetch        (WINDOW *win)
  1471. {
  1472.     int cnt;
  1473.  
  1474.     if (ungot_char != -1)
  1475.     {
  1476.         chtype ch = ungot_char;
  1477.         ungot_char = -1;
  1478.         return ch;
  1479.     }
  1480.  
  1481.     if (Kbcount <= 0)
  1482.     {
  1483.         Kbptr = Kbbuf;
  1484.  
  1485.         if ((cnt = get_input(win, Kbbuf, sizeof(Kbbuf),
  1486.                              Cbreak, Raw)) == ERR || cnt == 0)
  1487.             return ERR;
  1488.  
  1489.         Kbcount = cnt;
  1490.     }
  1491.  
  1492.     Kbcount--;
  1493.     return *(Kbptr++);
  1494. }
  1495.  
  1496. /*
  1497.  * wgetstr() - Get a string from keyboard.  Input is terminated by return
  1498.  *    or newline (which is stripped from string and replaced with null termination).
  1499.  */
  1500.  
  1501. EXPORT int wgetstr        (WINDOW *win, char *str)
  1502. {
  1503.     int i, ungot_off, cnt, c;
  1504.  
  1505.     if (ungot_char != -1)
  1506.     {
  1507.         if ((*(str) = (ungot_char & A_CHARTEXT)) == '\n' || *str == '\r')
  1508.         {
  1509.             ungot_char = -1;
  1510.             *str = '\0';
  1511.             return OK;
  1512.         }
  1513.         ungot_off = 1;
  1514.         ungot_char = -1;
  1515.     }
  1516.     else ungot_off = 0;
  1517.  
  1518.     if (Kbcount <= 0)
  1519.     {
  1520.         Kbptr = Kbbuf;
  1521.  
  1522.         if ((cnt = get_input(win, Kbbuf, sizeof(Kbbuf),
  1523.                              FALSE, FALSE)) == ERR || cnt == 0)
  1524.             return ERR;
  1525.  
  1526.         Kbcount = cnt;
  1527.     }
  1528.  
  1529.     for (i = 0; i < Kbcount - 1; i++)
  1530.         *(str + ungot_off + i) = Kbbuf[i] & A_CHARTEXT;
  1531.  
  1532.     if ((c = (Kbbuf[i] & A_CHARTEXT)) != '\n' && c != '\r')
  1533.         *(str + ungot_off + i++) = c;
  1534.  
  1535.     Kbcount = 0;
  1536.     *(str + ungot_off + i) = '\0';
  1537.     return OK;
  1538. }
  1539.  
  1540. #ifdef VSSCANF
  1541.  
  1542. /*
  1543.  * scanw() - Read a scanf()-formatted string from stdscr.
  1544.  */
  1545.  
  1546. EXPORT int    scanw        (char *fmt, ...)
  1547. {
  1548.     va_list args;
  1549.     int rtn;
  1550.  
  1551.     if (wgetstr(stdscr, _curses_prntw) == ERR)
  1552.         return ERR;
  1553.  
  1554.     va_start(args, fmt);
  1555.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1556.     va_end(args);
  1557.  
  1558.     return rtn;
  1559. }
  1560.  
  1561. /*
  1562.  * mvscanw() - Read a scanf()-formatted string from stdscr after positioning.
  1563.  */
  1564.  
  1565. EXPORT int    mvscanw    (int y, int x, char *fmt, ...)
  1566. {
  1567.     va_list args;
  1568.     int rtn;
  1569.  
  1570.     move(y, x);
  1571.  
  1572.     if (wgetstr(stdscr, _curses_prntw) == ERR)
  1573.         return ERR;
  1574.  
  1575.     va_start(args, fmt);
  1576.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1577.     va_end(args);
  1578.  
  1579.     return rtn;
  1580. }
  1581.  
  1582. /*
  1583.  * wscanw() - Read a scanf()-formatted string from a window.
  1584.  */
  1585.  
  1586. EXPORT int    wscanw        (WINDOW *win, char *fmt, ...)
  1587. {
  1588.     va_list args;
  1589.     int rtn;
  1590.  
  1591.     if (wgetstr(win, _curses_prntw) == ERR)
  1592.         return ERR;
  1593.  
  1594.     va_start(args, fmt);
  1595.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1596.     va_end(args);
  1597.  
  1598.     return rtn;
  1599. }
  1600.  
  1601. /*
  1602.  * mvwscanw() - Read a scanf()-formatted string from a window after positioning.
  1603.  */
  1604.  
  1605. EXPORT int    mvwscanw    (WINDOW *win, int y, int x, char *fmt, ...)
  1606. {
  1607.     va_list args;
  1608.     int rtn;
  1609.  
  1610.     wmove(win, y, x);;
  1611.  
  1612.     if (wgetstr(win, _curses_prntw) == ERR)
  1613.         return ERR;
  1614.  
  1615.     va_start(args, fmt);
  1616.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1617.     va_end(args);
  1618.  
  1619.     return rtn;
  1620. }
  1621.  
  1622. /*
  1623.  * vwscanw() - Read a scanf()-formatted string from a window using a
  1624.  * variable argument list.
  1625.  */
  1626.  
  1627. EXPORT int    vwscanw    (WINDOW *win, char *fmt, va_list ap)
  1628. {
  1629.     va_list args;
  1630.  
  1631.     if (wgetstr(win, _curses_prntw) == ERR)
  1632.         return ERR;
  1633.  
  1634.     return VSSCANF(_curses_prntw, fmt, ap);
  1635. }
  1636.  
  1637. #endif /* VSSCANF */
  1638.  
  1639. /*
  1640.  * flushinp() - Flush input queue
  1641.  */
  1642.  
  1643. EXPORT int    flushinp    (void)
  1644. {
  1645.     Kbcount = 0;
  1646.     Kbptr = Kbbuf;
  1647.  
  1648.  #ifdef CURS_FLUSHINP_FN
  1649.      CURS_FLUSHINP_FN();
  1650.  #endif
  1651.  
  1652.     return OK;
  1653. }
  1654.